//------------------------------------------------------------------------------
// Fichiers d'ent�te utilis�s
//------------------------------------------------------------------------------
#include "Gradiant.hpp"
#include <GL/gl.h>
#include "Tools/Logger.hpp"
#include <math.h>

//------------------------------------------------------------------------------
// Définition de constantes
//------------------------------------------------------------------------------

namespace ImageAnalysis
{

	//----------------------------------------------------------------------
	// Constructeur
	//----------------------------------------------------------------------
	Gradiant::Gradiant( int width, int height ):
	Layer(width, height)
	{
		int gradiantSize = width*height;
		
		// Allocation de la structure contenant les normes et les orientations
		// des pixels
		gradiantNorms				= new unsigned char [gradiantSize];
		gradiantOrientations 			= new float [gradiantSize];
		gradiantApproximateOrientations 	= new Orientation::TDirection[gradiantSize];
		
		// Initialisation du gradiant
		for( int index=0; index < gradiantSize; ++index )
		{	
			gradiantNorms[index] = 0;
			gradiantOrientations[index] = 0;
			gradiantApproximateOrientations[index] = Orientation::DIRECTION_0;
		}
	}

	//----------------------------------------------------------------------
	// Destructeur
	//----------------------------------------------------------------------
	Gradiant::~Gradiant( )
	{
        if( gradiantNorms != 0 )
        {   delete gradiantNorms; }

        if( gradiantOrientations != 0 )
        {
		delete gradiantOrientations; }
		
		if( gradiantApproximateOrientations != 0 )
        	{   delete gradiantApproximateOrientations; }
	}

    	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	void Gradiant::Draw()
	{
		glDrawPixels( layerWidth, layerHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, gradiantNorms );

		int sample = 0;
		int sampleRatio = 10;
		float sizeVector = 15;
		// Dessin des orientations du gradiants
		glColor3i(255,0,0);
		glBegin( GL_LINES );
		for( int y=0; y < layerHeight; ++y )
		{
			for( int x=0; x < layerWidth; ++x )	
			{				
				int index = x + y*layerWidth;				
				if( (gradiantNorms[index] > 50) )
				{
					if( sample%sampleRatio == 0)	
					{
						float angle = gradiantOrientations[index]*(M_PI/180.0f);
						glColor3f(1.0f,0.0f,0.0f);
						glVertex2d(x,y);				
						glVertex2d(x + cos( angle )*sizeVector ,y + sin( angle )*sizeVector );
					}
					++sample;
				}
			}
		}
		glEnd();
	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	unsigned char Gradiant::GetGradiantNorm( int index )
	{
        return gradiantNorms[index];
	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	float Gradiant::GetGradiantOrientation( int index )
	{
        return gradiantOrientations[index];
	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	Orientation::TDirection Gradiant::GetGradiantApproximatedOrientation( int index )
	{
        return gradiantApproximateOrientations[index];
	}

	
    //----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	void Gradiant::SetGradiantNorm( int index, unsigned char norm )
	{
        	gradiantNorms[index] = norm;
	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	void Gradiant::SetGradiantOrientation( int index, float orientation )
	{
		// Enregistrement de la valeur exacte de l'orientation du gradiant
		gradiantOrientations[index] = orientation;

		// Enregistrement de la direction approxim�de l'orientation du 
		// gradiant
		gradiantApproximateOrientations[index] = Orientation::ConvertAngleToDirection(orientation);
	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------	
	Histogram* Gradiant::GetHistogram( Region* region )
	{
		// Création de l'histogramme
		Histogram* histogram = new Histogram( 256 );
		
		// Si la région est nulle alors on parcours toutes l'image
		if( region == 0 )
		{
			// Parcours de tous les pixels de l'image
			int regionSize = layerWidth*layerHeight;
			for( int index=0; index < regionSize; ++index )
			{	
				histogram->AddPixelToValue( gradiantNorms[ index ] );
			}
		}
		else
		{			
			// Parcours de tous les pixels de la région
			for( int j=region->Y; j < region->Y+region->Height; ++j )
			{
				for( int i=region->X; i < region->X+region->Width; ++i )
				{
					int index = i+j*layerWidth;
					histogram->AddPixelToValue( gradiantNorms[ index ] );
				}
			}
		}

		return histogram;
	}

    //----------------------------------------------------------------------
    // Permet de calculer la moyenne des valeurs dans une r�ion donn�
    //----------------------------------------------------------------------
/*
    int Gradiant::GetMeanValueOfRegion( int* region, int regionSize )
	{
		int mean = 0;
		for( int index=0; index < regionSize; ++index )
		{
			mean += gradiantNorms[ region[index] ];
		}
		
		return mean/regionSize;
	}

    //----------------------------------------------------------------------
    // Permet de calculer l'�art type des valeurs dans une r�ion donn�
    //----------------------------------------------------------------------
    int Gradiant::GetStandardDeviationValueOfRegion( int* region, int regionSize, int mean )
	{
		int standardDeviation = 0;
		for( int index=0; index < regionSize; ++index )
		{
			standardDeviation += gradiantNorms[ region[index] ] - mean;
		}
		
		return standardDeviation/regionSize;
	}
*/

}


